package dxunderground.utilities.security;

import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class SecureEncoder {
	public static void main(String[] args) throws Exception {
		if (args == null || args.length < 3) {
			System.out.println("Usage: java SecureEncoder <algorithm> <text> <secretKey>");
			return;
		}
		SecureEncoder theEncoder = new SecureEncoder(args[0], args[2]);
		if (theEncoder.isValid(args[1])) {
			System.out.println("decryption result is '" + theEncoder.decode(args[1]) + "'");
		}
	}

	private final transient Cipher theCipher;

	private final transient SecretKeySpec theKey;

	/**
	 * @param pAlgorithm
	 * @param pPassPhrase
	 */
	public SecureEncoder(String anAlgorithm, String aPassPhrase) throws NoSuchAlgorithmException, GeneralSecurityException {
		theKey = new SecretKeySpec(aPassPhrase.getBytes(), anAlgorithm);
		theCipher = Cipher.getInstance(anAlgorithm);
	}

	public String decode(final String secret) throws GeneralSecurityException {
		final BigInteger n = new BigInteger(secret, 16);
		final byte[] encoding = n.toByteArray();

		theCipher.init(Cipher.DECRYPT_MODE, theKey);
		final byte[] decode = theCipher.doFinal(encoding);
		return new String(decode);
	}

	/**
	 * encrypt a string using the pass phrase & algorithm
	 * 
	 * @param secret
	 *            = the string to encode
	 */
	public String encode(final String secret) throws GeneralSecurityException {
		theCipher.init(Cipher.ENCRYPT_MODE, theKey);
		final byte[] encoding = theCipher.doFinal(secret.getBytes());
		final BigInteger n = new BigInteger(encoding);
		return n.toString(16);
	}

	public boolean isValid(final String encodedString) throws GeneralSecurityException {
		try {
			decode(encodedString);
		} catch (Exception e) {
			throw new GeneralSecurityException("Failed to decode encoded string");// ,
			// e);
		}
		return true;
	}
}